import { uniqBy } from 'lodash-es'
import { In, Like } from 'typeorm'
import dayjs from 'dayjs'

import { datasource } from '../../db/index.js'

import roleEntity from '../../model/roleModel.js'
import menuModel from '../../model/menuModel.js'
import userModel from '../../model/userModel.js'

const roleRepository = datasource.getRepository(roleEntity)
const menuRepository = datasource.getRepository(menuModel)
const userRepository = datasource.getRepository(userModel)

/**
 * 分页查询 - 角色列表
 */
export const roleList = async (req, res) => {
  let { pageSize = 20, currentPage = 1, ...rest } = req.body

  let roleName = rest.roleName !== undefined ? rest.roleName.trim() : rest.roleName

  let query = {}

  if (rest.status !== '' && rest.status !== undefined) {
    query.status = rest.status
  }

  if (roleName) {
    query.roleName = Like(`%${roleName}%`)
  }
  console.log('【角色分页】-查询条件')
  console.log(query)

  let result = await roleRepository
    .createQueryBuilder('role')
    .where(query)
    .take(pageSize)
    .skip((currentPage - 1) * pageSize)
    .orderBy('updateTime', 'DESC')
    .getManyAndCount()

  if (result[0].length) {
    result[0].forEach((p) => {
      p.statusText = p.status === 1 ? '启用' : '禁用'
      p.updateTime = dayjs(p.updateTime).format('YYYY-MM-DD HH:mm:ss')
    })

    // 查询出用户名
    let updateIds = result[0].filter((p) => p.updateId !== undefined && p.updateId !== null).map((p) => p.updateId)

    if (updateIds.length) {
      // 查询出用户id
      let userList = await userRepository
        .createQueryBuilder('user')
        .select(['user.userId', 'user.name'])
        .where('user.userId In(:...list)', {
          list: updateIds
        })
        .getMany()

      // 查找修改人
      if (userList.length) {
        let current = null

        result[0].forEach((p1) => {
          p1.updateUserName = null
          current = userList.find((p2) => p1.updateId === p2.userId)

          if (current) {
            p1.updateUserName = current.name
          }
        })

        current = null
      }
    }
  }

  res.json({
    code: 1000,
    data: {
      list: result[0],
      total: result[1]
    },
    message: '操作成功'
  })
}

export const createRole = async (req, res) => {
  let { roleName, menuList, desc } = req.body

  let exitRole = await roleRepository.findOne({
    where: {
      roleName: roleName
    }
  })

  if (exitRole) {
    res.json({
      code: -1,
      data: null,
      message: '已经存在角色' + roleName
    })
    return
  }

  let menus = []

  if (menuList && menuList.length) {
    // 根据权限id查询全部的权限实体
    menus = await menuRepository.find({
      where: {
        menuId: In(menuList)
      }
    })
  }

  const result = await roleRepository.save({
    roleName,
    desc,
    // 这里一定是使用从数据库查询出来的引用对象，不然关联表是没法创建到数据的
    // 注意： 这里字段 menus 是必须和 roleModel里面的 relations.[key] relations.menus 一样，否则就找不到关联关系，关联表就无法新增数据
    menus: menus
  })

  res.json({
    code: 1000,
    data: result,
    message: '操作成功'
  })
}

/**
 * 更新角色
 */
export const updateRole = async (req, res) => {
  let { roleId, roleName, menuList, desc } = req.body

  roleName = roleName ? roleName.trim() : null

  try {
    // 先判断角色是否存在
    let roleItem = await roleRepository.findOne({
      where: {
        roleId
      }
    })

    if (!roleItem) {
      res.json({
        code: -1,
        data: null,
        message: '角色不存在'
      })
      return
    }

    // 判断角色名称是否重复
    if (roleName) {
      let duplicateRow = await roleRepository.findOne({
        where: {
          roleName
        }
      })

      if (duplicateRow && duplicateRow.roleId !== Number(roleId)) {
        res.json({
          code: -1,
          data: null,
          message: '角色名称重复'
        })
        return
      }
    }

    let menuListResult = []

    if (menuList && menuList.length) {
      // In操作符， menuIds 数量多了，可能存在性能问题， 可以做分片， 多次In
      menuListResult = await menuRepository.find({
        where: {
          menuId: In(menuList)
        }
      })
    }

    roleItem.updateId = req.userId

    roleItem.roleName = roleName
    roleItem.desc = desc
    roleItem.menus = menuListResult
    roleItem.updateTime = dayjs().format('YYYY-MM-DD HH:mm:ss')

    await roleRepository.save(roleItem)

    res.json({
      code: 1000,
      data: null,
      message: '操作成功'
    })
  } catch (error) {
    res.json({
      code: -1,
      data: null,
      message: '操作失败' + error.message
    })
  }
}

export const deleteRole = async (req, res) => {}

/**
 * 查询角色详情
 */
export const detailRole = async (req, res) => {
  let id = req.query.id

  try {
    let roleItem = await roleRepository
      .createQueryBuilder('role')
      .where('role.roleId = :roleId', {
        roleId: id
      })
      .leftJoinAndSelect('role.menus', 'menu')
      .getOne()

    if (!roleItem) {
      res.json({
        code: -1,
        data: null,
        message: '未查询到角色详情'
      })
      return
    }

    roleItem.menus = roleItem.menus.map((p) => p.menuId)

    roleItem.statusText = roleItem.status === 1 ? '启用' : '禁用'

    roleItem.updateTime = dayjs(roleItem.updateTime).format('YYYY-MM-DD HH:mm:ss')
    roleItem.createTime = dayjs(roleItem.createTime).format('YYYY-MM-DD HH:mm:ss')

    // 这里仅仅返回菜单的id List 给前端回显
    res.json({
      code: 1000,
      data: roleItem,
      messaeg: '操作成功'
    })
  } catch (error) {
    console.log(error)
    res.json({
      code: -1,
      data: null,
      message: '操作失败' + error.message
    })
  }
}

export const getMenuListByRole = async (req, res) => {
  // 查询用户所有角色， 角色关联了菜单
  let userInfo = await userRepository
    .createQueryBuilder('user')
    .leftJoinAndSelect('user.roles', 'role')
    .leftJoinAndSelect('role.menus', 'menu')
    .select(['user.name', 'user.userId', 'role.roleId', 'role.roleName', 'menu'])
    .where({
      userId: req.userId
    })
    .orderBy('menu.menuOrder', 'ASC')
    .getOne()

  let allMenuList = []
  // 将所有的menus先合并为一个数组
  userInfo.roles.forEach((item) => {
    allMenuList = allMenuList.concat(item.menus)
  })

  // console.log('未去重菜单之前的长度', allMenuList.length);

  // 对菜单去重
  let tree = uniqBy(allMenuList, (item) => item.menuId)

  // console.log('tree', tree.length);

  tree = covertToTree(tree, null)

  res.json({
    code: 1000,
    data: tree,
    message: '操作成功'
  })
}

/**
 * 启用-禁用
 */
export const updateRoleStatus = async (req, res) => {
  const { roleId, status } = req.body

  try {
    let row = await roleRepository.findOne({
      where: {
        roleId: roleId
      }
    })

    if (!row) {
      res.json({
        code: -1,
        data: null,
        messaeg: '角色不存在'
      })
      return
    }

    row.updateTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
    row.status = Number(status)

    await roleRepository.save(row)

    res.json({
      code: 1000,
      data: null,
      message: '操作成功'
    })
  } catch (error) {
    console.log(error)
    res.json({
      code: -1,
      data: [],
      message: '操作失败' + error.message
    })
  }
}

/**
 * 查询所有角色
 */
export const getAllRoleList = async (req, res) => {
  try {
    let result = await roleRepository
      .createQueryBuilder('role')
      .select(['role.roleId', 'role.roleName'])
      .where('role.status =:status', {
        status: 1
      })
      .getMany()

    res.json({
      code: 1000,
      data: result,
      messaeg: '操作成功'
    })
  } catch (error) {
    res.json({
      code: -1,
      data: [],
      messaeg: '操作失败' + error.message
    })
  }
}
